//
//  EAGLView.mm
//  RnD_02_rolling_spheres
//
//  Created by Goffredo Marocchi on 7/22/10.
//  Copyright __MyCompanyName__ 2010. All rights reserved.
//

//File modified by Goffredo Marocchi (this is not the original SIO2 provided file,
//sio2 and its creator ROm are not responsible for the content of this file as it is now

#import <QuartzCore/QuartzCore.h>
#import <OpenGLES/EAGLDrawable.h>
#import "glues.h"

#import "EAGLView.h"
#import "RnD_02_rolling_spheresAppDelegate.h"
#import "main.h"
#import "RnD_02_rolling_spherestemplate.h"
#import "SysTools.h"

id sio2GLView = nil;

#define DISPLAY_LINK ([SysTools isOS:@"3.1" strict:NO])
//#define DISPLAY_LINK (0)

/*
 Use the define below to toggle (comment the line) between the simulator rotation movement or
 the device (accelerometer) movement.
 */	
//#define USE_SIMULATOR 1
//
//


// A class extension to declare private methods
@interface EAGLView ()

@property (nonatomic, retain) EAGLContext *context;

- (BOOL) createFramebuffer;
- (void) destroyFramebuffer;

@end


@implementation EAGLView

@synthesize context;
@synthesize animationInterval;


// You must implement this
+ (Class)layerClass {
	return [CAEAGLLayer class];
}


//The GL view is stored in the nib file. When it's unarchived it's sent -initWithCoder:
- (id)initWithCoder:(NSCoder*)coder {
	
	if ((self = [super initWithCoder:coder])) {
		// Get the layer
		CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
		
		eaglLayer.opaque = YES;
		eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
										[NSNumber numberWithBool:NO], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];
		
		context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
		
		if (!context || ![EAGLContext setCurrentContext:context]) {
			[self release];
			return nil;
		}
		
		animationInterval = 1.0f / 60.0f;
		
		displayLink = nil;
		animationTimer = nil;
		
		displayLinkSupported = DISPLAY_LINK;
		
		isAnimating = FALSE;
	}
	sio2GLView = self;
	return self;
}

- (void)drawView {
	
	
	if( sio2->_SIO2window->_SIO2windowrender )
	{
		sio2->_SIO2window->_SIO2windowrender();
		
		sio2WindowSwapBuffers( sio2->_SIO2window );
		if (displayLinkSupported) sio2->_SIO2window->d_time = [displayLink duration];
	}
	
	
	glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
	[context presentRenderbuffer:GL_RENDERBUFFER_OES];
}


- (void)layoutSubviews {
	[EAGLContext setCurrentContext:context];
	[self destroyFramebuffer];
	[self createFramebuffer];
	[self drawView];
}



- (BOOL)createFramebuffer {
	
	glGenFramebuffersOES(1, &viewFramebuffer);
	glGenRenderbuffersOES(1, &viewRenderbuffer);
	
	glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
	glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
	[context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer];
	glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);
	
	glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
	glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
	
	glGenRenderbuffersOES(1, &depthRenderbuffer);
	glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
	glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES, backingWidth, backingHeight);
	glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
	
	if( !sio2 )
	{
		// Initialize SIO2 global variable
		sio2Init( &tmp_argc, tmp_argv );
		
		// Initialize OpenGL ES
		sio2InitGL();
		
		// Initialize OpenAL
		sio2InitAL();
		
		// Create a window using the default sio2 structure handle
		sio2->_SIO2window = sio2WindowInit();
		
		sio2->_SIO2resource = sio2ResourceInit((char*) "default" );
		// Update the viewport with the current window size
		sio2WindowUpdateViewport( sio2->_SIO2window, 0, 0, backingWidth, backingHeight );
		
		// Attach a function to the render callback
		//sio2->_SIO2window->_SIO2windowrender = templateRender;
		sio2->_SIO2window->_SIO2windowrender = templateLoader;
		
		// Specify the function callback to use when the application quit.
		sio2WindowShutdown( sio2->_SIO2window, templateShutdown );
		
		// Link the appropriate callbacks to handle tap, move and the
		// accelerometer.
		sio2->_SIO2window->_SIO2windowtap			= templateScreenTap;
		sio2->_SIO2window->_SIO2windowtouchmove		= templateScreenTouchMove;
		sio2->_SIO2window->_SIO2windowaccelerometer = templateScreenAccelerometer;
		
	}
	
	return YES;
}

- (void)destroyFramebuffer {
	
	glDeleteFramebuffersOES(1, &viewFramebuffer);
	viewFramebuffer = 0;
	glDeleteRenderbuffersOES(1, &viewRenderbuffer);
	viewRenderbuffer = 0;
	
	if(depthRenderbuffer) {
		glDeleteRenderbuffersOES(1, &depthRenderbuffer);
		depthRenderbuffer = 0;
	}
}


- (void)startAnimation {
	int frame_rate_skip = animationInterval*60.0f; //frame_rate_skip has to be >=1
	
#if DEBUG==1
	NSLog(@"Frame rate skip = %i", frame_rate_skip);
#endif
	
    if (!isAnimating)
    {
        if (displayLinkSupported)
        {
            // CADisplayLink is API new to iPhone SDK 3.1. Compiling against earlier versions will result in a warning, but can be dismissed
            // if the system version runtime check for CADisplayLink exists in -initWithCoder:. The runtime check ensures this code will
            // not be called in system versions earlier than 3.1.
			
			NSLog(@"DisplayLink used");
			
            displayLink = [NSClassFromString(@"CADisplayLink") displayLinkWithTarget:self selector:@selector(drawView)];
            [displayLink setFrameInterval:frame_rate_skip];
            [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
        }
        else {
            animationTimer = [NSTimer scheduledTimerWithTimeInterval:animationInterval target:self 
															selector:@selector(drawView) userInfo:nil repeats:TRUE];
			NSLog(@"NSTimer used");
		}
        isAnimating = TRUE;
    }
	
}

- (void)stopAnimation {
    if (isAnimating)
    {
        if (displayLinkSupported)
        {
            [displayLink invalidate];
            displayLink = nil;
        }
        else
        {
            [animationTimer invalidate];
            animationTimer = nil;
        }
        isAnimating = FALSE;
    }
}

- (void)setAnimationInterval:(NSTimeInterval)interval {
    if (interval >= 1)
    {
        animationInterval = interval;
		
        if (isAnimating)
        {
            [self stopAnimation];
            [self startAnimation];
        }
    }
}


- (void)dealloc {
	
	if ([EAGLContext currentContext] == context) {
		[EAGLContext setCurrentContext:nil];
	}
	
	[context release];	
	[super dealloc];
}


-(id) getDelegate {
	RnD_02_rolling_spheresAppDelegate* mainDelegate = (RnD_02_rolling_spheresAppDelegate*)[[UIApplication sharedApplication] delegate];
	return mainDelegate;
}

- (CGSize)frame_size { return [self frame].size;}

@end
